package controllers

import (
	"net/http"
	"strings"
	"time"

	"xinmanpan/app/models"
	"xinmanpan/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type UserController struct {
	BaseController
}

func NewUserController(db *gorm.DB) *UserController {
	return &UserController{
		BaseController{
			DB: db,
		},
	}
}

// @Summary 用户注册
// @Description 返回用户注册是否成功信息。
// @Tags 用户auth
// @Accept json
// @Produce json
// @Param user body models.XinmanUser true "用户信息"
// @Success 200 {object} map[string]string
// @Router /register [post]
func (uc *UserController) Register(c *gin.Context) {
	var user models.XinmanUser
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": "invalid_request", "message": "Invalid request", "data": nil})
		return
	}

	// 密码加密
	var xinmanHasher utils.XinmanHasher
	sha256Password := xinmanHasher.Sha256(user.Password)
	user.Password = sha256Password

	uuid := utils.GetUUID()
	user.Uuid = uuid

	user.CreateTime = time.Now()
	user.UpdateTime = time.Now()
	user.Sort = time.Now().UnixNano()

	// 保存到数据库
	if err := uc.DB.Create(&user).Error; err != nil {
		// 重复错误
		if strings.Contains(err.Error(), "Duplicate entry") && strings.Contains(err.Error(), "email") {
			c.JSON(http.StatusConflict, gin.H{"message": "Email already exists", "code": "email_exists", "data": nil})
			return
		} else if strings.Contains(err.Error(), "Duplicate entry") && strings.Contains(err.Error(), "username") {
			c.JSON(http.StatusConflict, gin.H{"message": "Username already exists", "code": "username_exists", "data": nil})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to create user", "code": "failed_create_user", "data": nil})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "User registered successfully", "code": "ok", "data": nil})
}

// @Summary 用户登录
// @Description 返回用户登录相关信息。
// @Tags 用户auth
// @Accept json
// @Produce json
// @Param user body models.XinmanUser true "用户信息"
// @Success 200 {object} map[string]string
// @Router /login [post]
func (uc *UserController) Login(c *gin.Context) {
	var loginData, dbUser models.XinmanUser

	if err := c.ShouldBindJSON(&loginData); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"message": "Invalid request", "code": "invalid_request", "data": nil})
		return
	}

	// 查找用户
	if err := uc.DB.Where("username = ?", loginData.Username).First(&dbUser).Error; err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"message": "Invalid username or password", "code": "invalid_username_or_password", "data": nil})
		return
	}

	// 验证密码
	var xinmanHasher utils.XinmanHasher
	loginData.Password = xinmanHasher.Sha256(loginData.Password)
	if dbUser.Password != loginData.Password {
		c.JSON(http.StatusUnauthorized, gin.H{"message": "Invalid username or password", "code": "invalid_username_or_password", "data": nil})
		return
	}

	// 生成 Access Token 和 Refresh Token
	accessToken, err := utils.GenerateToken(loginData.Username, utils.AccessTokenSecret, 2*time.Minute)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to generate access token", "code": "failed_generate_access_token", "data": nil})
		return
	}

	refreshToken, err := utils.GenerateToken(loginData.Username, utils.RefreshTokenSecret, 7*24*time.Hour)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to generate refresh token", "code": "failed_generate_refresh_token", "data": nil})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Login successful", "code": "ok", "data": utils.TokenResponse{
		AccessToken:  accessToken,
		RefreshToken: refreshToken,
	}})

	// c.JSON(http.StatusOK, gin.H{"message": "Login successful"})
}

// @Summary 刷新Token
// @Description 返回token相关信息。
// @Tags 用户auth
// @Accept json
// @Produce json
// @Param Authorization header string true "Refresh Token"
// @Success 200 {object} map[string]string
// @Router /refresh [post]
func (uc *UserController) Refresh(c *gin.Context) {
	refreshTokenWithBearer := c.GetHeader("Authorization")
	refreshToken := strings.TrimPrefix(refreshTokenWithBearer, "Bearer ")
	if refreshToken == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"message": "Refresh token required", "code": "refresh_token_required", "data": nil})
		return
	}

	// 验证 Refresh Token
	claims, err := utils.ValidateToken(refreshToken, utils.RefreshTokenSecret)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"message": "Invalid refresh token", "code": "invalid_refresh_token", "data": nil})
		return
	}

	// 生成新的 Access Token 和新的 Refresh Token
	username := claims["username"].(string)
	accessToken, err := utils.GenerateToken(username, utils.AccessTokenSecret, 2*time.Minute)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to generate new access token", "code": "failed_generate_new_access_token", "data": nil})
		return
	}

	// 生成新的 Refresh Token
	newRefreshToken, err := utils.GenerateToken(username, utils.RefreshTokenSecret, 7*24*time.Hour)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate new refresh token", "code": "failed_generate_new_refresh_token", "data": nil})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Token refreshed successfully", "code": "ok",
		"data": utils.TokenResponse{AccessToken: accessToken,
			RefreshToken: newRefreshToken,
		}})
}

// 受保护的路由
func (uc *UserController) Protected(c *gin.Context) {

	value, exists := c.Get("username")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
		return
	}
	// 返回受保护资源
	c.JSON(http.StatusOK, gin.H{
		"message": "Protected content",
		"user":    value,
	})
}
